﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ppt = Microsoft.Office.Interop.PowerPoint;

namespace ObjectModel.PowerPoint
{
    public static class TextRangeExtensions
    {
        public static Ppt.TextRange GetParentTextRange(this Ppt.TextRange textRange)
        {
            return textRange.GetParent<Ppt.TextFrame>().TextRange;
        }

        public static bool IntersectsWith(this Ppt.TextRange textRange, Ppt.TextRange textRangeToCompare)
        {
            int start1 = textRangeToCompare.Start;
            int end1 = textRangeToCompare.Start + textRangeToCompare.Length;
            int start2 = textRange.Start;
            int end2 = textRange.Start + textRange.Length;
            
            return textRange.GetParent<Ppt.Shape>() == textRangeToCompare.GetParent<Ppt.Shape>() &&
                   (start1 < start2 && end1 > start2 ||
                   start1 < end2 && end1 > end2 ||
                   start1 >= start2 && end1 <= end2);
        }

        public static bool IntersectsWithSelection(this Ppt.TextRange textRange)
        {
            Ppt.TextRange selectedTextRange = Globals.Application.ActiveWindow.Selection.TextRange;

            return textRange.IntersectsWith(selectedTextRange);
        }

        public static bool Contains(this Ppt.TextRange textRange, Ppt.TextRange textRangeToCompare)
        {
            int start1 = textRangeToCompare.Start;
            int end1 = textRangeToCompare.Start + textRangeToCompare.Length;
            int start2 = textRange.Start;
            int end2 = textRange.Start + textRange.Length;

            return textRange.GetParent<Ppt.Shape>() == textRangeToCompare.GetParent<Ppt.Shape>() &&
                   start1 >= start2 && end1 <= end2;
        }

        public static bool ContainsSelection(this Ppt.TextRange textRange)
        {
            Ppt.TextRange selectedTextRange = Globals.Application.ActiveWindow.Selection.TextRange;

            return textRange.Contains(selectedTextRange);
        }

        public static bool IsSelected(this Ppt.TextRange textRange)
        {
            Ppt.Selection sel = Globals.Application.ActiveWindow.Selection;

            if (sel.Type == Ppt.PpSelectionType.ppSelectionText)
            {
                Ppt.TextRange selectedTextRange = sel.TextRange;

                return textRange.GetParent<Ppt.Shape>() == sel.TextRange.GetParent<Ppt.Shape>() &&
                       textRange.Start >= sel.TextRange.Start &&
                       textRange.Start + textRange.Length <= sel.TextRange.Start + sel.TextRange.Length;
            }
            else
                return false;
        }

        public static void AddToSelection(this Ppt.TextRange textRange)
        {
            Ppt.TextRange selectedTextRange = Globals.Application.ActiveWindow.Selection.TextRange;

            textRange.Union(selectedTextRange).Select();
        }

        static Ppt.TextRange Union(this Ppt.TextRange textRange, Ppt.TextRange textRangeToInclude)
        {
            // Check that the two TextRanges are from the same parent Shape.
            if (textRange.GetParent<Ppt.Shape>() != textRangeToInclude.GetParent<Ppt.Shape>())
                throw new ArgumentException("Both TextRanges are not from the same parent Shape");

            int start = Math.Min(textRange.Start, textRangeToInclude.Start);
            int end = Math.Max(textRange.Start + textRange.Length, textRangeToInclude.Start + textRangeToInclude.Length);
            int length = end - start;

            return textRange.GetParentTextRange().Characters(start, length);
        }

        public static void RemoveFromSelection(this Ppt.TextRange textRange)
        {
            Ppt.TextRange selectedTextRange = Globals.Application.ActiveWindow.Selection.TextRange;

            int start = -1;
            int length = -1;
            if (selectedTextRange.Start <= textRange.Start)
            {
                start = selectedTextRange.Start;
                length = textRange.Start - selectedTextRange.Start;
            }
            else if (selectedTextRange.Start + selectedTextRange.Length >= textRange.Start + textRange.Length)
            {
                start = textRange.Start + textRange.Length;
                length = (selectedTextRange.Start + selectedTextRange.Length) - (textRange.Start + textRange.Length);
            }
            else
                throw new InvalidOperationException("TextRange is not currently selected.");

            textRange.GetParentTextRange().Characters(start, length).Select();
        }
    }
}
